#include "RingBuffer.h"


CRingBuffer::CRingBuffer()
{
	m_totalBytes = 0;
	m_bufferPtr = NULL;
	m_avail = 0;
	m_wpos = 0;
	m_rpos = 0;
}

CRingBuffer::~CRingBuffer()
{
}

bool CRingBuffer::Create(int totalBytes)
{
	m_bufferPtr = new uint8_t[totalBytes];
	if (NULL == m_bufferPtr) {
		return false;
	}

	m_totalBytes = totalBytes;
	Reset();
	return true;
}

void CRingBuffer::Destroy()
{
	if (NULL != m_bufferPtr) {
		delete[] m_bufferPtr;
		m_bufferPtr = NULL;
	}
	m_totalBytes = 0;
	Reset();
}

void CRingBuffer::Reset()
{
	if (NULL != m_bufferPtr) {
		memset(m_bufferPtr, 0x00, m_totalBytes);
	}
	m_avail = 0;
	m_wpos = 0;
	m_rpos = 0;
}

bool CRingBuffer::Put(int size, const uint8_t *data)
{
	if (m_avail + size > m_totalBytes) {
		return false;
	}

	if (m_rpos > m_wpos) {
		memcpy(m_bufferPtr + m_wpos, data, size);
	}
	else {
		int space = m_totalBytes - m_wpos;
		if (space >= size) {
			memcpy(m_bufferPtr + m_wpos, data, size);
		}
		else {
			memcpy(m_bufferPtr + m_wpos, data, space);
			memcpy(m_bufferPtr, data + space, size - space);
		}
	}
	
	m_wpos = (m_wpos + size) % m_totalBytes;
	m_avail += size;
	return true;
}

bool CRingBuffer::Get(int size, uint8_t *data)
{
	if (size > m_avail)
		return false;

	if (m_rpos < m_wpos) {
		memcpy(data, m_bufferPtr + m_rpos, size);
	}
	else {
		int space = m_totalBytes - m_rpos;
		if (space >= size) {
			memcpy(data, m_bufferPtr + m_rpos, size);
		}
		else {
			memcpy(data, m_bufferPtr + m_rpos, space);
			memcpy(data + space, m_bufferPtr, size - space);
		}
	}

	m_rpos = (m_rpos + size) % m_totalBytes;
	m_avail -= size;
	return true;
}

int CRingBuffer::Available()
{
	return m_avail;
}

int CRingBuffer::Free()
{
	return (m_totalBytes - m_avail);
}

uint8_t CRingBuffer::Peek()
{
	return Peek(0);
}

uint8_t CRingBuffer::Peek(int pos)
{
	if (m_avail <= pos) {
		return 0x00;
	}

	pos = (m_rpos + pos) % m_totalBytes;
	return m_bufferPtr[pos];
}

void CRingBuffer::Skip()
{
	uint8_t c;
	Get(1, &c);
}

void CRingBuffer::Skip(int cnt)
{
	while (cnt > 0) {
		Skip();
		cnt--;
	}
}

